home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / utmisc1 / fscode.lha / Src / Decode.c < prev    next >
C/C++ Source or Header  |  1995-05-22  |  6KB  |  310 lines

  1. /*
  2. ** $VER: Decode.c (22.5.95) by Flavio Stanchina
  3. */
  4.  
  5. #include <exec/types.h>
  6. #include <dos/dos.h>
  7. #include <dos/stdio.h>
  8.  
  9. #include <clib/exec_protos.h>
  10. #include <clib/utility_protos.h>
  11. #include <clib/dos_protos.h>
  12.  
  13. #include <ctype.h>
  14. #include <string.h>
  15.  
  16. #if defined(__SASC)
  17. #include <proto/exec.h>
  18. #include <proto/utility.h>
  19. #include <proto/dos.h>
  20. #endif
  21.  
  22. #include "FSCode.h"
  23. #include "CRC32.h"
  24.  
  25. BPTR OpenPart(struct FSData *fsd)
  26. {
  27. open_next:
  28.     /* For starters, open the input file when needed */
  29.     if (fsd->In == 0)
  30.     {
  31.         fsd->PhysPart += 1;
  32.  
  33.         if (fsd->Multi)
  34.             SPrintf(fsd->Temp, NameFmt, fsd->File, fsd->PhysPart);
  35.         else
  36.             strcpy(fsd->Temp, fsd->File);
  37.  
  38.         if (fsd->In = Open(fsd->Temp, MODE_OLDFILE))
  39.         {
  40.             SetVBuf(fsd->In, NULL, BUF_FULL, 16384);
  41.         }
  42.         else
  43.         {
  44.             if (!(fsd->Multi) || (fsd->PhysPart == 1))
  45.                 MyPrintFault(fsd, IoErr(), fsd->Temp);
  46.             return 0;
  47.         }
  48.     }
  49.  
  50.     /* Search a !start or !mstrt line */
  51.     while (FGets(fsd->In, fsd->Temp, sizeof(fsd->Temp)-1) != NULL)
  52.     {
  53.         STRPTR line = fsd->Temp + START_SKIP;
  54.         LONG part, parts;
  55.  
  56.         /* !start, single-part file */
  57.         if (Strnicmp(fsd->Temp, StartFmt, START_SKIP) == 0)
  58.         {
  59.             if (fsd->Part != fsd->Parts)
  60.             {
  61.                 FPuts(fsd->StdErr, "found a single-part header, was looking for a multi-part header\n");
  62.                 return 0;
  63.             }
  64.  
  65.             TrimLine(&line);
  66.             strcpy(fsd->Name, line);
  67.  
  68.             fsd->Size = 0;
  69.             fsd->CRC  = 0xFFFFFFFF; /* preload shift register, per CRC-32 spec */
  70.  
  71.             fsd->NumFound += 1;
  72.             fsd->Part = fsd->Parts = 0;
  73.         }
  74.         /* !mstrt, multi-part file */
  75.         else if (Strnicmp(fsd->Temp, MultiFmt, START_SKIP) == 0)
  76.         {
  77.             part  = GetDec(&line);
  78.             parts = GetDec(&line);
  79.             TrimLine(&line);
  80.  
  81.             if (part > parts)
  82.             {
  83.                 FPrintf(fsd->StdErr, "found part %ld/%ld", part, parts);
  84.                 FPuts(fsd->StdErr, ", which is impossible\n");
  85.                 return 0;
  86.             }
  87.  
  88.             fsd->Part += 1;
  89.  
  90.             if (fsd->Parts == 0)
  91.             {
  92.                 strcpy(fsd->Name, line);
  93.  
  94.                 fsd->Size = 0;
  95.                 fsd->CRC  = 0xFFFFFFFF; /* preload shift register, per CRC-32 spec */
  96.  
  97.                 fsd->NumFound += 1;
  98.                 fsd->Parts = parts;
  99.             }
  100.             else
  101.             {
  102.                 if (Stricmp(fsd->Name, line) != 0)
  103.                 {
  104.                     FPrintf(fsd->StdErr, "found part %ld/%ld", part, parts);
  105.                     FPrintf(fsd->StdErr, " of file \"%s\", was looking for file \"%s\"\n", line, fsd->Name);
  106.                     return 0;
  107.                 }
  108.  
  109.                 if ((part != fsd->Part) || (parts != fsd->Parts))
  110.                 {
  111.                     FPrintf(fsd->StdErr, "found part %ld/%ld", part, parts);
  112.                     VFPrintf(fsd->StdErr, ", was looking for part %ld/%ld\n", &(fsd->Part));
  113.                     return 0;
  114.                 }
  115.             }
  116.         }
  117.         /* nothing, try again */
  118.         else continue;
  119.  
  120.         fsd->BufPtr = fsd->Buffer;
  121.         fsd->BufCnt = 0;
  122.  
  123.         return fsd->In;
  124.     }
  125.  
  126.     /* If we get here, there wasn't a !start line in this file */
  127.     MyClose(fsd, fsd->In);
  128.     fsd->In = 0;
  129.  
  130.     if (fsd->Multi)
  131.         goto open_next;
  132.     else return 0;
  133. }
  134.  
  135. LONG FlushPart(struct FSData *fsd)
  136. {
  137.     if (fsd->BufCnt)
  138.     {
  139.         /* Try and open specified file for output. */
  140.         if (fsd->Out == 0)
  141.         {
  142.             if ((fsd->Out = Open((fsd->To ? fsd->To : fsd->Name), MODE_NEWFILE)) == 0)
  143.                 return -2;
  144.         }
  145.  
  146.         /* Update size and CRC. */
  147.         fsd->Size += fsd->BufCnt;
  148.         fsd->CRC = CRC32_blocks(fsd->Buffer, fsd->BufCnt, fsd->CRC);
  149.  
  150.         /* Write buffer to disk. */
  151.         fsd->BufPtr = fsd->Buffer;
  152.         if (Write(fsd->Out, fsd->BufPtr, fsd->BufCnt) != fsd->BufCnt) return -2;
  153.         fsd->BufCnt = 0;
  154.  
  155.         if (CheckSignal(SIGBREAKF_CTRL_C)) return -3;
  156.     }
  157.  
  158.     return 0;
  159. }
  160.  
  161. /*
  162. **
  163. ** RESULT
  164. **   0  all ok
  165. **  -2  error from FlushPart()
  166. **  -4  error closing input file
  167. */
  168. LONG ClosePart(struct FSData *fsd, LONG c)
  169. {
  170.     LONG tmp;
  171.  
  172.     if (tmp = FlushPart(fsd)) return tmp;
  173.  
  174.     /* This should be a !end line. Make sure... */
  175.     if (c == '!')
  176.     {
  177.         fsd->Temp[0] = c;
  178.         if (FGets(fsd->In, fsd->Temp+1, sizeof(fsd->Temp)-2) != NULL)
  179.         {
  180.             if (Strnicmp(fsd->Temp, EndFmt, 5) == 0)
  181.             {
  182.                 /* Check size and CRC against those saved in the !end line. */
  183.                 TEXT *line = fsd->Temp+5;
  184.                 fsd->RealSize = GetDec(&line);
  185.                 fsd->RealCRC  = GetHex(&line);
  186.                 c = 0;
  187.  
  188.                 if (fsd->Size != fsd->RealSize) FPuts(fsd->StdErr, "size mismatch\n");
  189.                 if (fsd->CRC  != fsd->RealCRC ) FPuts(fsd->StdErr, "CRC mismatch\n");
  190.             }
  191.         }
  192.     }
  193.  
  194.     /*
  195.     ** This is getting complex. Close the output file if:
  196.     **  - the user didn't specify an output file name;
  197.     **  - the file is open;
  198.     **  - we're at end of file (either single- or multi-part).
  199.     */
  200.     if ((fsd->To == NULL) && (fsd->Out != 0) && (fsd->Part == fsd->Parts))
  201.     {
  202.         MyClose(fsd, fsd->Out);
  203.         fsd->Out = 0;
  204.     }
  205.  
  206.     return c;
  207. }
  208.  
  209. /***** Skip characters outside the ASCII 33-126 range *****/
  210. #ifdef __SASC
  211. __inline
  212. #endif
  213. static LONG MyGetC(struct FSData *fsd)
  214. {
  215.     LONG c;
  216.  
  217.     do {
  218.         if ((c = FGetC(fsd->In)) < 0) break;
  219.     } while((c < '!') || (c > '~'));
  220.     return c;
  221. }
  222.  
  223. LONG Decode(struct FSData *fsd)
  224. {
  225.     LONG c;
  226.     LONG len;
  227.     ULONG tmp;
  228.  
  229.     while (1)
  230.     {
  231.         if (CheckSignal(SIGBREAKF_CTRL_C)) return -3;
  232.  
  233.         len = 0;
  234.         tmp = 0;
  235.  
  236.         /* 1 */
  237.         if ((c = MyGetC(fsd)) == ENDSTREAMCH) return -1;
  238.  
  239.         if (c == '!')
  240.         {
  241.             if ((c = ClosePart(fsd, c)) != 0)
  242.                 return c;
  243.  
  244.             if (OpenPart(fsd))
  245.                 continue;
  246.             else return 0;
  247.         }
  248.  
  249.         if (c != '#')
  250.         {
  251.             tmp += c - 42;
  252.             tmp *= 85;
  253.         }
  254.         else len = 3;
  255.  
  256.         /* 2 */
  257.         if ((c = MyGetC(fsd)) == ENDSTREAMCH) return -1;
  258.         if (c == '!') return c;
  259.         if (c != '#')
  260.         {
  261.             tmp += c - 42;
  262.             tmp *= 85;
  263.         }
  264.         else len = 2;
  265.  
  266.         /* 3 */
  267.         if ((c = MyGetC(fsd)) == ENDSTREAMCH) return -1;
  268.         if (c == '!') return c;
  269.         if (c != '#')
  270.         {
  271.             tmp += c - 42;
  272.             tmp *= 85;
  273.         }
  274.         else len = 1;
  275.  
  276.         /* 4 */
  277.         if ((c = MyGetC(fsd)) == ENDSTREAMCH) return -1;
  278.         if (c == '!') return c;
  279.         tmp += c - 42;
  280.         tmp *= 85;
  281.  
  282.         /* 5 */
  283.         if ((c = MyGetC(fsd)) == ENDSTREAMCH) return -1;
  284.         if (c == '!') return c;
  285.         tmp += c - 42;
  286.  
  287.         /* Put decoded data into output buffer, maybe flush buffer. */
  288.         switch(len)
  289.         {
  290.             case 3: fsd->BufPtr[2] = tmp; tmp >>= 8;
  291.             case 2: fsd->BufPtr[1] = tmp; tmp >>= 8;
  292.             case 1: fsd->BufPtr[0] = tmp;
  293.                 fsd->BufPtr += len;
  294.                 fsd->BufCnt += len;
  295.                 /* Always flush buffer when it gets misaligned. */
  296.                 if ((c = FlushPart(fsd)) != 0) return c;
  297.                 break;
  298.  
  299.             default:
  300.                 *(LONG *)fsd->BufPtr = tmp;
  301.                 fsd->BufPtr += 4;
  302.                 fsd->BufCnt += 4;
  303.  
  304.                 /* Flush buffer if it gets close to overflow. */
  305.                 if (fsd->BufCnt > FSD_BUFSIZ-4)
  306.                     if ((c = FlushPart(fsd)) != 0) return c;
  307.         }
  308.     }
  309. }
  310.